package com.mega.center.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mega.center.system.enums.SysEnums;
import com.mega.center.system.enums.msg.SysMsgEnum;
import com.mega.center.system.mapper.DictionaryMapper;
import com.mega.center.system.model.entity.Dictionary;
import com.mega.center.system.model.vo.DictionaryTreeVO;
import com.mega.center.system.service.IDictionaryService;
import com.mega.common.core.constant.UserConstants;
import com.mega.common.core.enums.CommonMsgEnum;
import com.mega.common.core.enums.CommonStatus;
import com.mega.common.core.exception.BusinessException;
import com.mega.common.core.utils.TreeUtil;
import com.mega.common.core.web.service.MegaBaseServiceImpl;
import com.mega.common.redis.utils.CodeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * 字典  服务实现
 *
 * @author Eric
 * @version 1.0
 * @since 2020-09-28
 */
@Service
public class DictionaryServiceImpl extends MegaBaseServiceImpl<DictionaryMapper, Dictionary> implements IDictionaryService {


    /**
     * 新增字典
     *
     * @param dictionary 字典 实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Dictionary dictionary) {
        dictionary.setParentDictCode(StrUtil.isBlank(dictionary.getParentDictCode()) ? UserConstants.DEFAULT_TREE_ROOT_CODE : dictionary.getParentDictCode());
        Integer nameCount = this.count(Wrappers.<Dictionary>lambdaQuery()
                .eq(Dictionary::getParentDictCode, dictionary.getParentDictCode())
                .eq(Dictionary::getDictName, dictionary.getDictName()));
        if (nameCount != null && nameCount > 0) {
            throw new BusinessException(CommonMsgEnum.NAME_REPEAT, dictionary.getDictName());
        }
        if (SysEnums.DictionaryType.DICTIONARY.getCode().equals(dictionary.getType())) {
            Integer codeCount = this.count(Wrappers.<Dictionary>lambdaQuery()
                    .eq(Dictionary::getDictCode, dictionary.getDictCode()));
            if (codeCount != null && codeCount > 0) {
                throw new BusinessException(CommonMsgEnum.CODE_REPEAT, dictionary.getDictCode());
            }
        } else {
            dictionary.setDictCode(CodeUtils.getDateCode(dictionary));
        }
        dictionary.setDictStatus(CommonStatus.NORMAL.getCode());
        checkParentDic(dictionary);
        //插入数据
        this.save(dictionary);
    }

    /**
     * 验证父节点是否存在，且不能为字典类型
     *
     * @param dictionary
     */
    private void checkParentDic(Dictionary dictionary) {
        String parentCode = dictionary.getParentDictCode();
        if (!UserConstants.DEFAULT_TREE_ROOT_CODE.equals(parentCode)) {
            Dictionary parentDictionary = Optional.ofNullable(getDictionaryByCode(parentCode)).orElseGet(() -> {
                throw new BusinessException(CommonMsgEnum.DATE_NOT_EXIST, parentCode);
            });
            if (SysEnums.DictionaryType.DICTIONARY.getCode().equals(parentDictionary.getType())) {
                throw new BusinessException(SysMsgEnum.DICTIONARY_HAS_CHILD);
            } else {
                dictionary.setTreeLevel(parentDictionary.getTreeLevel() + 1);
            }
        } else {
            dictionary.setTreeLevel(1);
        }
    }

    /**
     * 根据编码获取字典
     *
     * @param dictCode
     * @return
     */
    @Override
    public Dictionary getDictionaryByCode(String dictCode) {
        return this.getOne(Wrappers.<Dictionary>lambdaQuery().eq(Dictionary::getDictCode, dictCode));
    }

    /**
     * 编辑字典
     *
     * @param dictionary 字典 实体类
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Dictionary dictionary) {
        //判断数据是否为空
        Dictionary queryEntity = this.getById(dictionary.getId());
        if (queryEntity == null) {
            throw new BusinessException(CommonMsgEnum.DATE_NOT_EXIST);
        }
        //类型不能改
        if (!queryEntity.getType().equals(dictionary.getType())) {
            throw new BusinessException(SysMsgEnum.DICTIONARY_TYPE_CHANGE);
        }
        dictionary.setParentDictCode(StrUtil.isBlank(dictionary.getParentDictCode()) ? UserConstants.DEFAULT_TREE_ROOT_CODE : dictionary.getParentDictCode());
        //查询修改后名称是否与原先一致
        if (!dictionary.getDictName().equals(queryEntity.getDictName())) {
            Integer nameCount = this.count(Wrappers.<Dictionary>lambdaQuery()
                    .eq(Dictionary::getParentDictCode, dictionary.getParentDictCode())
                    .eq(Dictionary::getDictName, dictionary.getDictName()));
            if (nameCount != null && nameCount > 0) {
                throw new BusinessException(CommonMsgEnum.NAME_REPEAT, dictionary.getDictName());
            }
        }
        //查询修改后编码是否与原先一致
        if (!dictionary.getDictCode().equals(queryEntity.getDictCode())) {
            //判断编码是否重复
            Integer codeCount = this.count(Wrappers.<Dictionary>lambdaQuery()
                    .eq(Dictionary::getDictCode, dictionary.getDictCode()));
            if (codeCount != null && codeCount > 0) {
                throw new BusinessException(CommonMsgEnum.CODE_REPEAT, dictionary.getDictCode());
            }
        }
        if (!dictionary.getParentDictCode().equals(queryEntity.getParentDictCode())) {
            checkParentDic(dictionary);
        }
        //更新数据
        this.updateById(dictionary);
    }

    /**
     * 根据id删除字典
     *
     * @param id 主键值
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Integer id) {
        this.removeById(id);
    }

    /**
     * 获取树形字典
     */
    @Override
    public List<DictionaryTreeVO> listDictForTree() {
        List<DictionaryTreeVO> menuList = this.baseMapper.listDictForTree();
        return TreeUtil.buildTree(menuList, UserConstants.DEFAULT_TREE_ROOT_CODE);
    }

    /**
     * 获取子节点数据
     *
     * @param parentCode
     * @return
     */
    @Override
    public List<Dictionary> listChild(String parentCode) {
        return this.list(Wrappers.<Dictionary>lambdaQuery().eq(Dictionary::getParentDictCode, parentCode).orderByAsc(Dictionary::getDictSort));
    }
}
